<?php


namespace apps\marriage\core\service;


use apps\marriage\core\model\MatchmakerSpreadSalaryRecord;
use apps\marriage\core\model\MemberRechargeRecord;
use apps\marriage\core\model\PlatformAccountBook;
use apps\marriage\core\model\ServiceChargeOrder;
use apps\marriage\core\model\UserAccountBook;
use apps\marriage\core\payment\IPayOrder;
use think\Exception;
use think\facade\Log;
use vm\com\BaseModel;
use vm\com\BaseService;
use vm\org\lock\DisLockFactory;

class ServiceChargeOrderService extends BaseService implements IPayOrder
{
    private $rule = [
        'user_id' => 'number|>:0',
        'order_money' => 'number|>:0',
        'fromuid' => 'number'
    ];

    /**
     * @return ServiceChargeOrder
     */
    protected function getModel()
    {
        return new ServiceChargeOrder();
    }

    /**
     * @return UserService
     */
    protected function getUserService()
    {
        return service('User', SERVICE_NAMESPACE);
    }

    /**
     * @return UserAccountBookService
     */
    protected function getUserAccountBookService()
    {
        return service('UserAccountBook', SERVICE_NAMESPACE);
    }

    /**
     * @return PlatformAccountBookService
     */
    protected function getPlatformAccountBookService()
    {
        return service('PlatformAccountBook', SERVICE_NAMESPACE);
    }

    /**
     * @return MemberRechargeRecordService
     */
    private function getMemberRechargeRecordService()
    {
        return service('MemberRechargeRecord', SERVICE_NAMESPACE);
    }

    /**
     * @return BaseService|MatchmakerSpreadSalaryRecordService
     */
    private function getMatchmakerSpreadSalaryRecordService()
    {
        return service('MatchmakerSpreadSalaryRecord', SERVICE_NAMESPACE);
    }

    private function genSn()
    {
        while (true) {
            $sn = date('YmdHis') . rand_string(6, 1);
            if (!$this->getModel()->info(['order_sn' => $sn])) {
                return $sn;
            }
        }
    }

    public function createOrder(array $order)
    {
        $lockKey = 'lock_submit_service_charge_order';
        $lock = DisLockFactory::instance();
        $lock->lock($lockKey, 10);
        try {
            $order['order_sn'] = $this->genSn();
            $order['order_status'] = ServiceChargeOrder::ORDER_STATUS_CONFIRMED;
            $order['create_time'] = time();
            $order['pay_status'] = ServiceChargeOrder::PAY_STATUS_UNPAIED;
            $orderId = parent::create($order);
            return $order['order_sn'];
        } catch (Exception $e) {
            Log::error('FILE:' . $e->getFile());
            Log::error('LINE:' . $e->getLine());
            Log::error('MSG:' . $e->getMessage());
            throw new Exception('订单创建失败');
        } finally {
            $lock->unlock($lockKey);
        }
    }

    public function createOrderByUseGoldCoin(array $order)
    {
        $lockKey = 'lock_submit_service_charge_order';
        $lock = DisLockFactory::instance();
        $lock->lock($lockKey, 10);
        try {
            if($order['order_money'] > 0) {
                $this->getUserService()->decreaseGoldCoin($order['user_id'], $order['order_money'], false);
            }

            $order['order_sn'] = $this->genSn();
            $order['order_status'] = ServiceChargeOrder::ORDER_STATUS_FINISHED;
            $order['create_time'] = time();
            $order['pay_status'] = ServiceChargeOrder::PAY_STATUS_PAIED;
            $order['pay_time'] = time();
            $order['payment_name'] = '金币';

            $orderId = parent::create($order);
            if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_MEMBER_WXID) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_MEMBER_WXID,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_UNLOCK_MEMBER_WXID, $orderId, null, '解锁微信号');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_MEMBER_WXID, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_MEMBER_PHONE) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_MEMBER_PHONE,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_UNLOCK_MEMBER_PHONE, $orderId, null, '解锁手机号');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_MEMBER_PHONE, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_FACEID_DETECT) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_FACEID_DETECT,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_FACEID_DETECT, $orderId, null, '实名认证');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_FACEID_DETECT, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_ACTIVITY) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_ACTIVITY,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_ACTIVITY, $orderId, null, '参加活动');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_ACTIVITY, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_CHAT_SESSION) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_CHAT_SESSION,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_UNLOCK_CHAT_SESSION, $orderId, null, '解锁聊天');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_CHAT_SESSION, $orderId);
            }

            return $order['order_sn'];
        } catch (Exception $e) {
            Log::error('FILE:' . $e->getFile());
            Log::error('LINE:' . $e->getLine());
            Log::error('MSG:' . $e->getMessage());
            throw new Exception('订单创建失败');
        } finally {
            $lock->unlock($lockKey);
        }
    }

    public function getByOrderSn($orderSn)
    {
        $order = $this->getModel()->info(['order_sn' => $orderSn]);
        $order = $this->format($order);
        return $order;
    }

    public function format(array $order)
    {
        switch ($order['order_status']) {
            case ServiceChargeOrder::ORDER_STATUS_CANCELLED:
                $order['order_status_label'] = '已取消';
                break;
            case ServiceChargeOrder::ORDER_STATUS_UNCONFIRMED:
                $order['order_status_label'] = '未确认';
                break;
            case ServiceChargeOrder::ORDER_STATUS_REFUNDED:
                $order['order_status_label'] = '已退款';
                break;
            case ServiceChargeOrder::ORDER_STATUS_FINISHED:
                $order['order_status_label'] = '已完成';
                break;
            case ServiceChargeOrder::ORDER_STATUS_CONFIRMED:
                $order['order_status_label'] = '待付款';
                break;
            case ServiceChargeOrder::ORDER_STATUS_WAIT_SHIP:
                $order['order_status_label'] = '待发货';
                break;
            case ServiceChargeOrder::ORDER_STATUS_SHIPPED:
                $order['order_status_label'] = '已发货';
                break;
            case ServiceChargeOrder::ORDER_STATUS_REFUNDING:
                $order['order_status_label'] = '退款中';
                break;
            default:
                $order['order_status_label'] = 'N/A';
                break;
        }

        switch ($order['pay_status']) {
            case ServiceChargeOrder::PAY_STATUS_UNPAIED:
                $order['pay_status_label'] = '未付款';
                break;
            case ServiceChargeOrder::PAY_STATUS_PAIED:
                $order['pay_status_label'] = '已付款';
                break;
            default:
                $order['pay_status_label'] = 'N/A';
                break;
        }

        return $order;
    }

    /**
     * 创建支付交易后回调
     * @param $id
     * @param $tradeNo
     * @return bool|mixed|BaseService
     */
    public function onPayTradeCreated($id, $tradeNo)
    {
        return $this->updateByPk([
            'id' => $id,
            'pay_trade_no' => $tradeNo
        ]);
    }

    /**
     * 支付成功后回调
     * @param \app\common\payment\本站支付流水号|array $tradeNo
     * @param \app\common\payment\第三方支付平台流水号 $transactionId
     * @param \app\common\payment\付款时间 $payTime
     * @param \app\common\payment\支付方式名称 $paymentName
     * @return bool|mixed
     * @throws Exception
     */
    public function onPaySuccess($tradeNo, $transactionId, $payTime, $paymentName)
    {
        $order = $this->info([
            'pay_trade_no' => $tradeNo
        ]);
        if (!$order) {
            throw new Exception('订单不存在');
        }
        return $this->payConfirm($order['id'], $payTime, $paymentName, $transactionId);
    }

    /**
     * 后台确认已付款
     * @param $orderId              订单ID
     * @param $payTime              付款时间
     * @param $payPlatformName      支付平台名称
     * @param $payPlatformTradeNo   支付平台流水号
     * @return bool
     * @throws
     */
    public function payConfirm($orderId, $payTime, $payPlatformName, $payPlatformTradeNo)
    {
        $order = $this->getByPk($orderId);
        if ($order['order_status'] != ServiceChargeOrder::ORDER_STATUS_CONFIRMED || $order['pay_status'] != ServiceChargeOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('只有已确认待付款订单才可确认付款');
        }
        $data = [
            'id' => $orderId,
            'order_status' => ServiceChargeOrder::ORDER_STATUS_FINISHED,
            'pay_status' => ServiceChargeOrder::PAY_STATUS_PAIED,
            'pay_time' => $payTime,
            'transaction_id' => $payPlatformTradeNo,
            'payment_name' => $payPlatformName
        ];
        if ($this->updateByPk($data)) {
            if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_MEMBER_WXID) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_MEMBER_WXID,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_UNLOCK_MEMBER_WXID, $orderId, null, '解锁微信号');
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['order_money'], PlatformAccountBook::IID_TYPE_UNLOCK_MEMBER_WXID, $orderId, null, '解锁微信号');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_MEMBER_WXID, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_MEMBER_PHONE) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_MEMBER_PHONE,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_UNLOCK_MEMBER_PHONE, $orderId, null, '解锁手机号');
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['order_money'], PlatformAccountBook::IID_TYPE_UNLOCK_MEMBER_PHONE, $orderId, null, '解锁手机号');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_MEMBER_PHONE, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_FACEID_DETECT) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_FACEID_DETECT,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_FACEID_DETECT, $orderId, null, '实名认证');
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['order_money'], PlatformAccountBook::IID_TYPE_FACEID_DETECT, $orderId, null, '实名认证');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_FACEID_DETECT, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_ACTIVITY) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_ACTIVITY,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_ACTIVITY, $orderId, null, '参加活动');
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['order_money'], PlatformAccountBook::IID_TYPE_ACTIVITY, $orderId, null, '参加活动');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_ACTIVITY, $orderId);
            } else if($order['iid_type'] == ServiceChargeOrder::IID_TYPE_UNLOCK_CHAT_SESSION) {
                $this->getMemberRechargeRecordService()->create([
                    'user_id' => $order['user_id'],
                    'iid' => $order['iid'],
                    'iid_type' => MemberRechargeRecord::IID_TYPE_UNLOCK_CHAT_SESSION,
                ]);
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['order_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_UNLOCK_CHAT_SESSION, $orderId, null, '解锁聊天');
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['order_money'], PlatformAccountBook::IID_TYPE_UNLOCK_CHAT_SESSION, $orderId, null, '解锁聊天');
                // 计算佣金
                $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_UNLOCK_CHAT_SESSION, $orderId);
            }
            return true;
        }
        throw new Exception('操作失败');
    }
}